
#pragma once

#include <ql/config.h>
#include <ql/error.h>

#ifdef __cplusplus
extern "C"
{
#endif

/*
 * functions that manages ql allocator context
 */

struct QlAllocContext;
struct QlObj;

typedef void (* QlAllocFailureCallback)(struct QlAllocContext * c, QlErr error);


void ql_alloc_emit_error(struct QlAllocContext * c, QlErr error);

void ql_set_alloc_failure_callback(struct QlAllocContext * c, QlAllocFailureCallback failure_callback_p);

struct QlAllocContext * ql_create_alloc_context();

void ql_free_alloc_context(struct QlAllocContext * c);


/*
 * allocators for objects
 */

/*
 * allocates empty list
 */
struct QlCdr * ql_alloc_cdr(struct QlAllocContext * c);


/*
 * allocates identifier or returns existing one
 */
struct QlId * ql_alloc_id(struct QlAllocContext *  c, const char * id_str);

struct QlId * ql_alloc_id_len(struct QlAllocContext *  c, const char * id_str, size_t id_len);

/*
 * retrieves string associated with the token within Id given
 */
const char * ql_get_id_str(const struct QlId * id);

/*
 * atomic objects allocator: for integer, double and string types
 */

struct QlInt * ql_alloc_integer(struct QlAllocContext * c, int val);

struct QlDouble * ql_alloc_double(struct QlAllocContext * c, double val);

struct QlString * ql_alloc_string(struct QlAllocContext * c, const char * str);

struct QlString * ql_alloc_string_len(struct QlAllocContext * c, const char * str, size_t str_len);

/*
 * t/nil atoms
 */
struct QlObj * ql_get_t();

struct QlObj * ql_get_nil();

/*
 * garbage collector-related routines
 */
bool ql_gc_keep_alive(struct QlAllocContext * c, struct QlObj * obj, bool keep_alive);

void ql_gc_collect(struct QlAllocContext * c);

#ifdef QL_GC_DEBUG
void ql_gc_register_dispose_callback(struct QlAllocContext * c,
                                     void * context,
                                     void (* dispose_callback)(void * context, struct QlObj * disposed_obj));
#endif

#ifdef __cplusplus
}
#endif
